package com.yunshipei.core.manager;

import android.content.Context;
import android.text.TextUtils;

import com.yunshipei.core.common.DataJSCallback;
import com.yunshipei.core.common.DeviceInfo;
import com.yunshipei.core.common.XCloudException;
import com.yunshipei.core.model.AdapterApplication;
import com.yunshipei.core.model.ConfigInfo;
import com.yunshipei.core.model.UWAApplication;
import com.yunshipei.core.net.EnterClient;
import com.yunshipei.core.net.ServiceApi;
import com.yunshipei.core.net.convert.JsonConverterFactory;
import com.yunshipei.core.utils.StringUtils;

import org.json.JSONArray;
import org.json.JSONObject;
import org.reactivestreams.Publisher;

import java.util.ArrayList;
import java.util.List;

import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.BiFunction;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

/**
 * 更新适配包和运行时下载信息以及所有的适配包的manifest数据
 * <p>
 * 提供给Enterplorer的九宫格下拉刷新功能，刷新后需要更新九宫格的dataJS，此后适配包的下载也依赖于此，下拉刷新后需要更新本地存在的
 * 适配包以及适配包的配置信息。
 */
public class UpdateAppsHandler {

    private String uuid;
    private String companyId;
    private Context context;

    private ConfigInfo configInfo;
    private ServiceApi serviceApi;

    public UpdateAppsHandler(Context context, String uuid, String companyId) {
        this.context = context;
        this.uuid = uuid;
        this.companyId = companyId;
        configInfo = XCloud2Map.getInstance().getConfigInfo();
        serviceApi = new Retrofit.Builder().client(EnterClient.getInstances().getManagerClient()).baseUrl(configInfo.getUrl()).addConverterFactory(JsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build().create(ServiceApi.class);
    }

    public void start(final DataJSCallback dataJSCallback) {
        Flowable.zip(dataJSFlowable(), manifestFlowable(), new BiFunction<JSONObject, JSONArray, JSONObject>() {
            @Override
            public JSONObject apply(JSONObject jsonObject, JSONArray jsonArray) throws Exception {
                //更新manifest数据，返回dataJS内容
                List<String> appScops = new ArrayList<>();
                List<AdapterApplication> adapterApplications = XCloud2Map.getInstance().getConfigInfo().getAdapterApplications();
                for (AdapterApplication adapterApplication : adapterApplications) {
                    String scope = StringUtils.getZipPkgDownloadUrlFileName(adapterApplication.getDownloadUrl());
                    if (!TextUtils.isEmpty(scope)) {
                        appScops.add(scope);
                    }
                }
                JSONArray filterJSONArray = new JSONArray();
                for (int i = 0; i < jsonArray.length(); i++) {
                    JSONObject dataObject = jsonArray.optJSONObject(i);
                    if (dataObject != null) {
                        String tempScope = dataObject.optString("scope");
                        if (!TextUtils.isEmpty(tempScope) && appScops.contains(tempScope)) {
                            filterJSONArray.put(dataObject);
                        }
                    }
                }
                jsonArray = filterJSONArray;
                XCloud2Map.getInstance().updateManifestData(jsonArray);
                return jsonObject;
            }
        }).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<JSONObject>() {
            @Override
            public void accept(JSONObject jsonObject) throws Exception {
                dataJSCallback.success(jsonObject.toString());
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                String errorMsg = XCloudSDKManager.getInstance().generateError(throwable);
                dataJSCallback.error(errorMsg);
            }
        });
    }

    //更新本地适配包信息
    private Flowable<JSONObject> dataJSFlowable() {
        return serviceApi.dataJS(companyId, uuid, new DeviceInfo(context).allInfo()).flatMap(new Function<JSONObject, Publisher<JSONObject>>() {
            @Override
            public Publisher<JSONObject> apply(JSONObject jsonObject) throws Exception {
                int status = jsonObject.optInt("status", 0);
                if (1 == status) {
                    JSONObject data = jsonObject.optJSONObject("data");
                    if (data == null) {
                        return Flowable.error(new XCloudException("接口异常..."));
                    }
                    JSONObject incrementalVersionsObject = data.optJSONObject("incrementalVersions");
                    if (incrementalVersionsObject != null) {
                        JSONArray adapterPkgJSONArray = incrementalVersionsObject.optJSONArray("applications");
                        List<AdapterApplication> adapterApplications = new ArrayList<>();
                        if (adapterPkgJSONArray != null) {
                            int len = adapterPkgJSONArray.length();
                            for (int i = 0; i < len; i++) {
                                JSONObject adapterPkgObject = adapterPkgJSONArray.optJSONObject(i);
                                String downloadUrl = adapterPkgObject.optString("downloadUrl", "");
                                String appId = adapterPkgObject.optString("appId", "");
                                String version = adapterPkgObject.optString("version", "");
                                if (!TextUtils.isEmpty(downloadUrl) && !TextUtils.isEmpty(appId) && !TextUtils.isEmpty(version)) {
                                    AdapterApplication adapterApplication = new AdapterApplication(downloadUrl, appId, version);
                                    adapterApplications.add(adapterApplication);
                                }
                            }
                        }
                        configInfo.setAdapterApplications(adapterApplications);
                        JSONArray uwaPkgApplications = incrementalVersionsObject.optJSONArray("universalWebApps");
                        List<UWAApplication> uwaApplications = new ArrayList<>();
                        if (uwaPkgApplications != null) {
                            int len = uwaPkgApplications.length();
                            for (int i = 0; i < len; i++) {
                                JSONObject uwaJSONObject = uwaPkgApplications.optJSONObject(i);
                                String downloadUrl = uwaJSONObject.optString("downloadUrl", "");
                                String appId = uwaJSONObject.optString("appId", "");
                                String version = uwaJSONObject.optString("version", "");
                                if (!TextUtils.isEmpty(downloadUrl) && !TextUtils.isEmpty(appId) && !TextUtils.isEmpty(version)) {
                                    UWAApplication uwaApplication = new UWAApplication(downloadUrl, appId, version);
                                    uwaApplications.add(uwaApplication);
                                }
                            }
                        }
                        configInfo.setUWAApplications(uwaApplications);
                        //删除接口没有，但本地存在的多余适配包和小程序包
                        new LocalPackageManager(context, adapterApplications, uwaApplications).updateLocalApps();
                        return Flowable.just(data);
                    } else {
                        return Flowable.error(new XCloudException("接口不支持此功能"));
                    }
                }
                return Flowable.error(new XCloudException(jsonObject.optString("message", "未知接口异常，请联系管理员")));
            }
        }).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io());
    }

    //更新manifest数据信息
    private Flowable<JSONArray> manifestFlowable() {
        return serviceApi.allManifest(companyId, uuid).flatMap(new Function<JSONObject, Publisher<JSONArray>>() {
            @Override
            public Publisher<JSONArray> apply(JSONObject jsonObject) throws Exception {
                int status = jsonObject.optInt("status", 0);
                if (1 == status) {
                    JSONArray data = jsonObject.optJSONArray("data");
                    if (data == null) {
                        data = new JSONArray("[]");
                    }
                    return Flowable.just(data);
                }
                return Flowable.error(new XCloudException(jsonObject.optString("message", "未知接口异常，请联系管理员")));
            }
        }).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io());
    }
}
